package org.xjtu.weteam.common.aspect;

import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.xjtu.weteam.common.annotation.LogAction;
import org.xjtu.weteam.common.annotation.LogExecutionTime;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.xjtu.weteam.common.repository.LogRepository;
import java.util.Arrays;
import org.aspectj.lang.reflect.MethodSignature;
import java.sql.Timestamp;
import org.xjtu.weteam.model.domain.Log;
import org.xjtu.weteam.model.domain.User;
import org.xjtu.weteam.common.utils.SecurityUtils;


/**
 * 日志切面类
 * @author Kevin
 */
@Aspect
@Component
@Slf4j
public class LoggingAspect {

    @Autowired
    private LogRepository logRepository;

    @Around("@annotation(logExecutionTime)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint, LogExecutionTime logExecutionTime) throws Throwable {
        long start = System.currentTimeMillis();

        // 执行目标方法
        Object proceed = joinPoint.proceed();

        long executionTime = System.currentTimeMillis() - start;

        log.info("Method {} execution time: {} milliseconds", joinPoint.getSignature(), executionTime);
        return proceed;
    }

    @Around("execution(* org.xjtu.weteam.service..*(..))")
    public Object logApiAccess(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        log.info("Request method: {}, Request path: {}, Request parameter: {}", request.getMethod(), request.getRequestURI(), Arrays.toString(joinPoint.getArgs()));

        Object response = joinPoint.proceed();

        log.info("Response data: {}", response);
        return response;
    }

    @AfterReturning("@annotation(logAction)")
    public void logAfter(JoinPoint joinPoint, LogAction logAction) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        Log log = new Log();
        log.setUserId(getCurrentUserId());
        log.setAction(logAction.action());
        log.setTargetType(logAction.targetType());
        log.setTargetId(getTargetId(joinPoint));
        log.setTimestamp(new Timestamp(System.currentTimeMillis()));
        log.setDetails("Method executed: " + signature.getName());

        logRepository.save(log);
    }

    private Integer getCurrentUserId() {
        User currentUser = SecurityUtils.getCurrentUserInfo();
        if (currentUser != null) {
            return currentUser.getUserId();
        }
        return null;
    }

    // 这样就限定了 targetId 是第一个参数
    // 当然，新增操作要复杂一些
    private Integer getTargetId(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        if (args.length > 0 && args[0] instanceof Integer) {
            return (Integer) args[0];
        }
        return null;
    }



}